﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Joy.Erp.Ufida.Core;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Volo.Abp;
using Volo.Abp.Caching;

namespace Joy.Erp.Ufida.ItemMasters
{
    public class ItemCategoryUfidaAppService : UfidaAppService, IItemCategoryUfidaAppService
    {
        private readonly IMemoryCache _memoryCache;
        protected ITokenUfidaAppService TokenUfidaAppService =>
            LazyServiceProvider.LazyGetRequiredService<ITokenUfidaAppService>();

        public ItemCategoryUfidaAppService(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }

        public async Task<ItemCategoryUfidaDto> GetAsync(long id)
        {
            var u9list = await GetAllAsync();
            return u9list.FirstOrDefault(x => x.ID == id);
        }

        public async Task<ItemCategoryUfidaDto> FindByCodeAsync(string code)
        {
            var u9list = await GetAllAsync();
            return u9list.FirstOrDefault(x => x.Code == code);
        }

        public async Task<List<ItemCategoryUfidaDto>> GetAllAsync()
        {
            var cacheKey = typeof(ItemCategoryUfidaAppService).FullName;
            if (!_memoryCache.TryGetValue(cacheKey, out List<ItemCategoryUfidaDto> cachedData))
            {
                cachedData = await GetAllFromApiAsync();
                _memoryCache.Set(
                    cacheKey,
                    cachedData,
                    new MemoryCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
                        Size = cachedData.Count,
                    }
                );
            }
            return cachedData;
        }

        private async Task<List<ItemCategoryUfidaDto>> GetAllFromApiAsync()
        {
            var token = await TokenUfidaAppService.GetTokenAsync();
            var queryUrl = TokenUfidaAppService.U9ApiConfig.BaseUrl.AppendSegments(
                $"webapi/QueryCommon/QueryInfoBySql"
            );

            var httpRequest = new HttpRequestMessage(HttpMethod.Post, queryUrl);
            httpRequest.Headers.Add("token", token);

            var sqlBuilder = new StringBuilder();
            sqlBuilder.Append("select ");
            sqlBuilder.Append("  'ItemCategory' as TableName ");
            sqlBuilder.Append("  , c.ID ");
            sqlBuilder.Append("  , c.Code ");
            sqlBuilder.Append("  , ctrl.[Name] ");
            sqlBuilder.Append("  , def.TreeRule ");
            sqlBuilder.Append("  , c.CreatedOn ");
            sqlBuilder.Append("from ");
            sqlBuilder.Append("  CBO_Category c ");
            sqlBuilder.Append("  inner join CBO_Category_Trl ctrl on ctrl.ID = c.ID and ctrl.SysMLFlag = 'zh-CN' ");
            sqlBuilder.Append("  inner join CBO_CategoryType ct on ct.ID = c.CategorySystem ");
            sqlBuilder.Append("  left join Base_KeyFlexSegment segment on segment.KeyFlexFieldStru = c.KeyFlexFieldStru and segment.Number = 1 ");
            sqlBuilder.Append("  left join Base_ValueSetDef def on def.ID = segment.ValueSetDef ");
            sqlBuilder.Append("where ct.IsMain = 1 ");

            var jsonObj = new { SqlString = sqlBuilder.ToString() };
            var jsonObjStr = JsonConvert.SerializeObject(jsonObj);
            httpRequest.Content = new StringContent(jsonObjStr, Encoding.UTF8, "application/json");
            Logger.LogInformation($"开始请求Api接口，接口地址: {queryUrl}, 正文内容: {jsonObjStr}");

            var httpClient = new HttpClient();
            var response = await httpClient.SendAsync(httpRequest);
            response.HandStatusCode(queryUrl);

            var responseContent = await response.Content.ReadAsStringAsync();
            Logger.LogInformation($"开始解析Api返回结果");

            try
            {
                var resultObj = JsonConvert.DeserializeObject<CommonDto<ItemCategoryUfidaDto>>(
                    responseContent
                );
                if (!resultObj.Success)
                    throw new BusinessException("BasicArchives:104").WithData(
                        "ErrorMessage",
                        resultObj.ResMsg
                    );

                Logger.LogInformation($"Api接口请求成功，返回数据{resultObj.Data.Count}条");

                return resultObj.Data;
            }
            catch (JsonException ex)
            {
                throw new BusinessException("BasicArchives:103", innerException: ex).WithData(
                    "DtoType",
                    typeof(CommonDto).Name
                );
            }
        }
    }
}
